package com.example.core;

import com.alibaba.fastjson.JSON;
import com.example.common.config.DynamicConfigManager;
import com.example.common.config.ServiceDefinition;
import com.example.common.config.ServiceInstance;
import com.example.common.util.NetUtils;
import com.example.common.util.ServiceUtil;
import com.example.common.util.TimeUtil;
import com.example.config.center.api.ConfigCenter;
import com.example.register.center.api.RegisterCenter;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

import static com.example.common.constants.BasicConst.COLON_SEPARATOR;

@Slf4j
public class Bootstrap {
    public static void main(String[] args) {

        // 加载网关核心静态配置
        Config config = ConfigLoader.getInstance().load(args);

        // 插件初始化
        // 配置中心管理器初始化，连接配置中心，监听配置的新增、修改、删除
        ConfigCenter configCenter = ServiceUtil.loadService(ConfigCenter.class);
        configCenter.init(config.getRegistryAddress(), config.getEnv());
        configCenter.subscribeRulesChange(rules -> DynamicConfigManager.getInstance().putAllRule(rules));

        // 连接注册中心，将注册中心的实例加载到本地
        RegisterCenter registerCenter = ServiceUtil.loadService(RegisterCenter.class);
        registerCenter.init(config.getRegistryAddress(), config.getEnv());
        // 网关注册
        // 构造网关服务定义和服务实例
        ServiceDefinition gatewayServiceDefinition = buildGatewayServiceDefinition(config);
        ServiceInstance gatewayServiceInstance = buildGatewayServiceInstance(config);
        registerCenter.register(gatewayServiceDefinition, gatewayServiceInstance);
        registerCenter.subscribeAllServices((serviceDefinition, serviceInstanceSet) -> {
            log.info("refresh service and instance: {} {}", serviceDefinition.getUniqueId(), JSON.toJSON(serviceInstanceSet));
            DynamicConfigManager manager = DynamicConfigManager.getInstance();
            manager.addServiceInstance(serviceDefinition.getUniqueId(), serviceInstanceSet);
            manager.putServiceDefinition(serviceDefinition.getUniqueId(), serviceDefinition);
        });

        // 启动容器
        Container container = new Container(config);
        container.start();

        // 服务优雅关机，注销网关
        // 收到kill信号时调用
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                registerCenter.deregister(gatewayServiceDefinition, gatewayServiceInstance);
                container.shutdown();
            }
        });

    }

    private static ServiceInstance buildGatewayServiceInstance(Config config) {
        String localIp = NetUtils.getLocalIp();
        int port = config.getPort();
        ServiceInstance serviceInstance = new ServiceInstance();
        serviceInstance.setServiceInstanceId(localIp + COLON_SEPARATOR + port);
        serviceInstance.setIp(localIp);
        serviceInstance.setPort(port);
        serviceInstance.setRegisterTime(TimeUtil.currentTimeMillis());
        return serviceInstance;
    }

    private static ServiceDefinition buildGatewayServiceDefinition(Config config) {
        ServiceDefinition serviceDefinition = new ServiceDefinition();
        serviceDefinition.setInvokerMap(Collections.EMPTY_MAP);
        serviceDefinition.setUniqueId(config.getApplicationName());
        serviceDefinition.setServiceId(config.getApplicationName());
        serviceDefinition.setEnvType(config.getEnv());
        return serviceDefinition;
    }

}
